<template>
  <el-form ref="form" :model="formData" :rules="rules">
    <el-table :data="tableData" row-key="id" border>
      <el-table-column type="index" label="序号" width="58" />
      <el-table-column
        v-for="item in columns"
        :key="item.prop"
        :prop="item.prop"
        :label="item.label"
        v-slot="{ row }"
      >
        <el-form-item :prop="item.prop" v-if="row.isEdit">
          <component :is="typeMapping[item.type] || 'el-input'" v-model="formData[item.prop]"></component>
        </el-form-item>
        <template v-else>{{ row[item.prop] }}</template>
      </el-table-column>
      <el-table-column
        label="操作"
        fixed="right"
        width="120"
        v-slot="{ row, $index }"
      >
        <template v-if="!row.isEdit">
          <el-button
            type="text"
            :disabled="!!tableData.find((item) => item.isEdit)"
            @click="editRow(row)"
            >编辑</el-button
          >
          <el-button type="text" @click="deleteRow($index)"
            >删除</el-button
          ></template
        >
        <template v-else>
          <el-button type="text" @click="saveData(row, $index)">保存</el-button>
          <el-button type="text" @click="cancelEdit(row, $index)"
            >取消</el-button
          >
        </template>
      </el-table-column>
    </el-table>
  </el-form>
</template>
<script lang="ts" setup>
import {
  ref,
  reactive,
  watch,
  toRefs,
  nextTick,
  h,
  resolveComponent,
} from "vue";
export interface Row {
  [key: string]: any;
}
export interface Column {
  prop: string;
  label: string;
  type: string;
}
const typeMapping: { [key: string]: string } = {
  input: "el-input",
  number: "el-input-number",
  switch: "el-switch",
};
let isNew = true;
const props = defineProps<{
  tableData: Row[];
  formInitData: Row;
  rules: object;
  columns: Column[];
}>();
const { tableData, formInitData } = toRefs(props);
const form = ref();
const formData = ref({ ...formInitData.value });
function editRow(row: Row) {
  row.isEdit = true;
  isNew = false;
  nextTick(() => {
    formData.value = { ...row };
  });
}
function saveData(row: Row, index: number) {
  form.value.validate((success: boolean) => {
    if (success) {
      tableData.value[index] = {
        ...formData.value,
        id: row.id,
        isEdit: false,
      };
      form.value.resetFields();
    }
  });
}
function cancelEdit(row: Row, index: number) {
  if (isNew) {
    tableData.value.splice(index, 1);
  } else {
    row.isEdit = false;
    isNew = true;
  }
  form.value.resetFields();
}
function deleteRow(index: number) {
  tableData.value.splice(index, 1);
}
</script>
<style scoped>
.el-form-item {
  margin-top: 20px;
}
</style>
